package com.mathdroid.gui.main.buffs;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;

import com.mathdroid.core.DroidStringWorker;
import com.mathdroid.gui.ImageLoader;
import com.mathdroid.model.EModelObserverEvent;
import com.mathdroid.model.IModelObserver;
import com.mathdroid.model.Model;
import com.mathdroid.model.buffs.BuffTemplate;
import com.mathdroid.model.buffs.GroupBuffDebuff;
import com.mathdroid.model.enums.EBuffType;

/**
 * This is a panel with a list of checkboxes for buffs.
 */
public class BuffGroup extends JPanel implements IModelObserver {
	/**
	 * Default UID.
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * The space between components.
	 */
	private static final int SPACING = 10;

	/**
	 * The constraints used to add this panel to the parent panel.
	 */
	private final GridBagConstraints parentC = new GridBagConstraints();
	
	/**
	 * List of checkboxes in this panel.
	 */
	private final LinkedList<JCheckBox> boxes = new LinkedList<JCheckBox>();
	
	/**
	 * List of labels for buff icons.
	 */
	private final LinkedList<JLabel> icons = new LinkedList<JLabel>();
	
	/**
	 * The constraints for components of this panel.
	 */
	private GridBagConstraints c = new GridBagConstraints();
	
	/**
	 * ImageLoader.
	 */
	private final ImageLoader il = new ImageLoader();
	
	/**
	 * The current index. This is used to add new Elements.
	 */
	private int index = 0;
	
	/**
	 * The type of this group.
	 */
	private EBuffType type = null;
	
	/**
	 * StringWorker.
	 */
	private final DroidStringWorker sw = new DroidStringWorker();
	
	/**
	 * Creates a panel with a titled border that contains checkboxes for a
	 * group of buffs.
	 * @param name The name of the group.
	 * @param gridy The vertical grid position in the parent grid bag.
	 * @param spacing The spacing of the parent components.
	 * @param gridWidth the columns of the parent grid bag.
	 * @param t The type of this group.
	 */
	public BuffGroup(
			final String name, final int gridy, 
			final int spacing, final int gridWidth, final EBuffType t) {
		this.type = t;
		
		Model.registerObserver(this);
		this.setLayout(new GridBagLayout());
		
		this.parentC.fill = GridBagConstraints.BOTH;
		this.parentC.gridx = 0;
		this.parentC.gridy = gridy;
		this.parentC.weighty = 1;
		this.parentC.weightx = 1;
		this.parentC.gridwidth = gridWidth;
		this.parentC.insets = new Insets(0, spacing, spacing, spacing);
		
		this.setBorder(BorderFactory.createTitledBorder(name));
	}
	
	/**
	 * Get the constraints for the parent grid bag.
	 * @return Constraints.
	 */
	public final GridBagConstraints getConstraints() {
		return this.parentC;
	}

	/**
	 * Add a checkbox to this panel.
	 * @param b GroupBuff.
	 */
	public final void addBuff(final GroupBuffDebuff b) {
		final JCheckBox cb = new JCheckBox(b.getName());
		final JLabel lbl = new JLabel(
				this.il.getGroupBuffIcon(b.getIconName()));
		
		cb.addActionListener(new ActionListener() {
			
			private final int k = index;
			
			@Override
			public void actionPerformed(final ActionEvent e) {
				final BuffTemplate t = Model.getProfile().getBuffTemplate();
				int k = 0;

				for (int i = 0; i < t.size(); i++) {
					if (t.get(i).getType() == type) {
						if (k == this.k) {
							t.get(i).setActive(cb.isSelected());
							Model.buffDebuffChanged();
						}
						k++;
					}
				}
			}
		});
		
		final String tip = "<html>" + this.sw.insertBreaks(b.getToolTipText()) 
							+ "</html>";
		
		cb.setToolTipText(tip);
		lbl.setToolTipText(tip);
		cb.setSelected(b.isActive());
		
		this.c.gridy = index;
		this.c.fill = GridBagConstraints.HORIZONTAL;
		this.c.insets = new Insets(SPACING, SPACING, 0, SPACING);
		
		this.c.gridx = 0;
		this.c.weightx = 0;
		this.add(lbl, this.c);
		
		this.c.insets = new Insets(SPACING, 0, 0, SPACING);
		this.c.gridx = 1;
		this.c.weightx = 1;
		this.add(cb, this.c);
		this.icons.add(lbl);
		this.boxes.add(cb);
		
		this.index++;
		
	}

	@Override
	public final void modelChanged(final EModelObserverEvent e) {
		if (e == EModelObserverEvent.PROFILE_LOADED 
				|| e == EModelObserverEvent.BUFFS_LOADED) {
			
			final BuffTemplate t = Model.getProfile().getBuffTemplate();
			/* 'k' is the index for this local list. */
			int k = 0;
			
			/* 'i' is the index for the complete buff list in the model. */
			for (int i = 0; i < t.size(); i++) {
				/* We are only interested in buffs that belong in this group. */
				if (t.get(i).getType() == this.type) {
					this.boxes.get(k).setSelected(t.get(i).isActive());
					k++;
				}
			}
		}
	}
	
	/**
	 * @return The amount of Buffs/Debuffs in this group.
	 */
	public final int getGroupSize() {
		return this.boxes.size();
	}
}
